home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Main.bin / MenuItem.java < prev    next >
Text File  |  1998-09-22  |  16KB  |  488 lines

  1. /*
  2.  * @(#)MenuItem.java    1.48 98/08/21
  3.  *
  4.  * Copyright 1995-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  * 
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14. package java.awt;
  15.  
  16. import java.awt.peer.MenuItemPeer;
  17. import java.awt.event.*;
  18. import java.io.ObjectOutputStream;
  19. import java.io.ObjectInputStream;
  20. import java.io.IOException;
  21.  
  22.  
  23. /**
  24.  * All items in a menu must belong to the class 
  25.  * <code>MenuItem</code>, or one of its subclasses.
  26.  * <p>
  27.  * The default <code>MenuItem</code> object embodies
  28.  * a simple labeled menu item. 
  29.  * <p>
  30.  * This picture of a menu bar shows five menu items:
  31.  * <IMG SRC="images-awt/MenuBar-1.gif" 
  32.  * ALIGN=CENTER HSPACE=10 VSPACE=7> 
  33.  * <br CLEAR=LEFT>
  34.  * The first two items are simple menu items, labeled 
  35.  * <code>"Basic"</code> and <code>"Simple"</code>. 
  36.  * Following these two items is a separator, which is itself
  37.  * a menu item, created with the label <code>"-"</code>. 
  38.  * Next is an instance of <code>CheckboxMenuItem</code> 
  39.  * labeled <code>"Check"</code>. The final menu item is a 
  40.  * submenu labeled <code>"More Examples"</code>, 
  41.  * and this submenu is an instance of <code>Menu</code>. 
  42.  * <p>
  43.  * When a menu item is selected, AWT sends an action event to 
  44.  * the menu item. Since the event is an
  45.  * instance of <code>ActionEvent</code>, the <code>processEvent</code> 
  46.  * method examines the event and passes it along to 
  47.  * <code>processActionEvent</code>. The latter method redirects the
  48.  * event to any <code>ActionListener</code> objects that have
  49.  * registered an interest in action events generated by this
  50.  * menu item. 
  51.  * <P> 
  52.  * Note that the subclass <code>Menu</code> overrides this behavior and 
  53.  * does not send any event to the frame until one of its subitems is 
  54.  * selected. 
  55.  *
  56.  * @version 1.48, 08/21/98
  57.  * @author Sami Shaio
  58.  */
  59. public class MenuItem extends MenuComponent {
  60.     boolean enabled = true;
  61.     String label;
  62.     String actionCommand;
  63.  
  64.     // The eventMask is ONLY set by subclasses via enableEvents.
  65.     // The mask should NOT be set when listeners are registered
  66.     // so that we can distinguish the difference between when
  67.     // listeners request events and subclasses request them.
  68.     long eventMask;
  69.  
  70.     transient ActionListener actionListener;
  71.  
  72.     private MenuShortcut shortcut = null;
  73.  
  74.     private static final String base = "menuitem";
  75.     private static int nameCounter = 0;
  76.  
  77.     /*
  78.      * JDK 1.1 serialVersionUID 
  79.      */
  80.     private static final long serialVersionUID = -21757335363267194L;
  81.  
  82.     /** 
  83.      * Constructs a new MenuItem with an empty label and no keyboard
  84.      * shortcut.
  85.      * @since    JDK1.1
  86.      */
  87.     public MenuItem() {
  88.     this("", null);
  89.     }
  90.  
  91.     /** 
  92.      * Constructs a new MenuItem with the specified label 
  93.      * and no keyboard shortcut. Note that use of "-" in
  94.      * a label is reserved to indicate a separator between 
  95.      * menu items. By default, all menu items except for 
  96.      * separators are enabled. 
  97.      * @param       label the label for this menu item. 
  98.      * @since       JDK1.0
  99.      */
  100.     public MenuItem(String label) {
  101.     this(label, null);
  102.     }
  103.  
  104.     /**
  105.      * Create a menu item with an associated keyboard shortcut. 
  106.      * Note that use of "-" in a label is reserved to indicate 
  107.      * a separator between menu items. By default, all menu 
  108.      * items except for separators are enabled. 
  109.      * @param       label the label for this menu item. 
  110.      * @param       s the instance of <code>MenuShortcut</code> 
  111.      *                       associated with this menu item. 
  112.      * @since       JDK1.1
  113.      */
  114.     public MenuItem(String label, MenuShortcut s) {
  115.     this.label = label;
  116.         this.shortcut = s;
  117.     }
  118.  
  119.     /**
  120.      * Construct a name for this MenuComponent.  Called by getName() when
  121.      * the name is null.
  122.      */
  123.     String constructComponentName() {
  124.         return base + nameCounter++;
  125.     }
  126.  
  127.     /**
  128.      * Creates the menu item's peer.  The peer allows us to modify the 
  129.      * appearance of the menu item without changing its functionality.
  130.      */
  131.     public void addNotify() {
  132.         synchronized (getTreeLock()) {
  133.         if (peer == null) {
  134.             peer = Toolkit.getDefaultToolkit().createMenuItem(this);
  135.         }
  136.         }
  137.     }
  138.  
  139.     /**
  140.      * Gets the label for this menu item.
  141.      * @return  the label of this menu item, or <code>null</code> 
  142.                        if this menu item has no label.
  143.      * @see     java.awt.MenuItem#setLabel
  144.      * @since   JDK1.0
  145.      */
  146.     public String getLabel() {
  147.     return label;
  148.     }
  149.  
  150.     /**
  151.      * Sets the label for this menu item to the specified label.
  152.      * @param     label   the new label, or <code>null</code> for no label.
  153.      * @see       java.awt.MenuItem#getLabel
  154.      * @since     JDK1.0
  155.      */
  156.     public synchronized void setLabel(String label) {
  157.     this.label = label;
  158.     MenuItemPeer peer = (MenuItemPeer)this.peer;
  159.     if (peer != null) {
  160.         peer.setLabel(label);
  161.     }
  162.     }
  163.  
  164.     /**
  165.      * Checks whether this menu item is enabled.
  166.      * @see        java.awt.MenuItem#setEnabled
  167.      * @since      JDK1.0
  168.      */
  169.     public boolean isEnabled() {
  170.     return enabled;
  171.     }
  172.  
  173.     /**
  174.      * Sets whether or not this menu item can be chosen.
  175.      * @param      b  if <code>true</code>, enables this menu item; 
  176.      *                       if <code>false</code>, disables it.
  177.      * @see        java.awt.MenuItem#isEnabled
  178.      * @since      JDK1.1
  179.      */
  180.     public synchronized void setEnabled(boolean b) {
  181.         enable(b);
  182.     }
  183.  
  184.     /**
  185.      * @deprecated As of JDK version 1.1,
  186.      * replaced by <code>setEnabled(boolean)</code>.
  187.      */
  188.     public synchronized void enable() {
  189.     enabled = true;
  190.     MenuItemPeer peer = (MenuItemPeer)this.peer;
  191.     if (peer != null) {
  192.         peer.enable();
  193.     }
  194.     }
  195.  
  196.     /**
  197.      * @deprecated As of JDK version 1.1,
  198.      * replaced by <code>setEnabled(boolean)</code>.
  199.      */
  200.     public void enable(boolean b) {
  201.         if (b) {
  202.         enable();
  203.     } else {
  204.         disable();
  205.     }
  206.     }
  207.  
  208.     /**
  209.      * @deprecated As of JDK version 1.1,
  210.      * replaced by <code>setEnabled(boolean)</code>.
  211.      */
  212.     public synchronized void disable() {
  213.     enabled = false;
  214.     MenuItemPeer peer = (MenuItemPeer)this.peer;
  215.     if (peer != null) {
  216.         peer.disable();
  217.     }
  218.     }
  219.  
  220.     /**
  221.      * Get the <code>MenuShortcut</code> object associated with this
  222.      * menu item, 
  223.      * @return      the menu shortcut associated with this menu item,
  224.      *                   or <code>null</code> if none has been specified.
  225.      * @see         java.awt.MenuItem#setShortcut
  226.      * @since       JDK1.1
  227.      */
  228.     public MenuShortcut getShortcut() {
  229.         return shortcut;
  230.     }
  231.  
  232.     /** 
  233.      * Set the <code>MenuShortcut</code> object associated with this
  234.      * menu item. If a menu shortcut is already associated with 
  235.      * this menu item, it is replaced.
  236.      * @param       s  the menu shortcut to associate 
  237.      *                           with this menu item.
  238.      * @see         java.awt.MenuItem#getShortcut
  239.      * @since       JDK1.1
  240.      */
  241.     public void setShortcut(MenuShortcut s) {
  242.         shortcut = s;
  243.     MenuItemPeer peer = (MenuItemPeer)this.peer;
  244.     if (peer != null) {
  245.         peer.setLabel(label);
  246.     }
  247.     }
  248.  
  249.     /**
  250.      * Delete any <code>MenuShortcut</code> object associated 
  251.      * with this menu item.
  252.      * @since      JDK1.1
  253.      */
  254.     public void deleteShortcut() {
  255.         shortcut = null;
  256.     MenuItemPeer peer = (MenuItemPeer)this.peer;
  257.     if (peer != null) {
  258.         peer.setLabel(label);
  259.     }
  260.     }
  261.  
  262.     /*
  263.      * Delete a matching MenuShortcut associated with this MenuItem.
  264.      * Used when iterating Menus.
  265.      */
  266.     void deleteShortcut(MenuShortcut s) {
  267.         if (s.equals(shortcut)) {
  268.             shortcut = null;
  269.             MenuItemPeer peer = (MenuItemPeer)this.peer;
  270.             if (peer != null) {
  271.                 peer.setLabel(label);
  272.             }
  273.         }
  274.     }
  275.  
  276.     /*
  277.      * Post an ActionEvent to the target (on 
  278.      * keydown).  Returns true if there is an associated 
  279.      * shortcut.
  280.      */
  281.     boolean handleShortcut(KeyEvent e) {
  282.         MenuShortcut s = new MenuShortcut(e.getKeyCode(), 
  283.                              (e.getModifiers() & InputEvent.SHIFT_MASK) > 0);
  284.         if (s.equals(shortcut) && enabled) {
  285.             // MenuShortcut match -- issue an event on keydown.
  286.             if (e.getID() == KeyEvent.KEY_PRESSED) {
  287.                 Toolkit.getEventQueue().postEvent(
  288.                           new ActionEvent(this, ActionEvent.ACTION_PERFORMED, 
  289.                                           actionCommand));
  290.             } else {
  291.                 // silently eat key release.
  292.             }
  293.             return true;
  294.     }
  295.         return false;
  296.     }
  297.  
  298.     MenuItem getShortcutMenuItem(MenuShortcut s) {
  299.         return (s.equals(shortcut)) ? this : null;
  300.     }
  301.  
  302.     /**
  303.      * Enables event delivery to this menu item for events 
  304.      * to be defined by the specified event mask parameter
  305.      * <p>
  306.      * Since event types are automatically enabled when a listener for 
  307.      * that type is added to the menu item, this method only needs 
  308.      * to be invoked by subclasses of <code>MenuItem</code> which desire to 
  309.      * have the specified event types delivered to <code>processEvent</code> 
  310.      * regardless of whether a listener is registered. 
  311.      * @param       eventsToEnable the event mask defining the event types.
  312.      * @see         java.awt.MenuItem#processEvent
  313.      * @see         java.awt.MenuItem#disableEvents
  314.      * @see         java.awt.Component#enableEvents
  315.      * @since       JDK1.1
  316.      */
  317.     protected final void enableEvents(long eventsToEnable) {
  318.         eventMask |= eventsToEnable;
  319.     }
  320.  
  321.     /**
  322.      * Disables event delivery to this menu item for events 
  323.      * defined by the specified event mask parameter.
  324.      * @param       eventsToDisable the event mask defining the event types.
  325.      * @see         java.awt.MenuItem#processEvent
  326.      * @see         java.awt.MenuItem#enableEvents
  327.      * @see         java.awt.Component#disableEvents
  328.      * @since       JDK1.1
  329.      */
  330.     protected final void disableEvents(long eventsToDisable) {
  331.         eventMask &= ~eventsToDisable;  
  332.     }  
  333.  
  334.     /**
  335.      * Sets the command name of the action event that is fired 
  336.      * by this menu item.
  337.      * <p>
  338.      * By default, the action command is set to the label of 
  339.      * the menu item.
  340.      * @param       command   the action command to be set 
  341.      *                                for this menu item.
  342.      * @see         java.awt.MenuItem#getActionCommand
  343.      * @since       JDK1.1
  344.      */
  345.     public void setActionCommand(String command) {
  346.         actionCommand = command;
  347.     }
  348.  
  349.     /**
  350.      * Gets the command name of the action event that is fired 
  351.      * by this menu item.
  352.      * @see         java.awt.MenuItem#setActionCommand
  353.      * @since       JDK1.1
  354.      */
  355.     public String getActionCommand() {
  356.         return (actionCommand == null? label : actionCommand);
  357.     }
  358.  
  359.     /**
  360.      * Adds the specified action listener to receive action events
  361.      * from this menu item.
  362.      * @param      l the action listener.
  363.      * @see        java.awt.event.ActionEvent
  364.      * @see        java.awt.event.ActionListener
  365.      * @see        java.awt.MenuItem#removeActionListener
  366.      * @since      JDK1.1
  367.      */ 
  368.     public synchronized void addActionListener(ActionListener l) {
  369.     actionListener = AWTEventMulticaster.add(actionListener, l);
  370.         newEventsOnly = true;    
  371.     }
  372.  
  373.     /**
  374.      * Removes the specified action listener so it no longer receives
  375.      * action events from this menu item.
  376.      * @param      l the action listener.
  377.      * @see        java.awt.event.ActionEvent
  378.      * @see        java.awt.event.ActionListener
  379.      * @see        java.awt.MenuItem#addActionListener
  380.      * @since      JDK1.1
  381.      */ 
  382.     public synchronized void removeActionListener(ActionListener l) {
  383.     actionListener = AWTEventMulticaster.remove(actionListener, l);
  384.     }
  385.  
  386.     /**
  387.      * Processes events on this menu item. If the event is an 
  388.      * instance of <code>ActionEvent</code>, it invokes 
  389.      * <code>processActionEvent</code>, another method 
  390.      * defined by <code>MenuItem</code>.
  391.      * <p>
  392.      * Currently, menu items only support action events.
  393.      * @param       e the event.
  394.      * @see         java.awt.MenuItem#processActionEvent
  395.      * @since       JDK1.1
  396.      */
  397.     protected void processEvent(AWTEvent e) {
  398.         if (e instanceof ActionEvent) {
  399.             processActionEvent((ActionEvent)e);     
  400.         }
  401.     }
  402.  
  403.     // REMIND: remove when filtering is done at lower level
  404.     boolean eventEnabled(AWTEvent e) {
  405.         if (e.id == ActionEvent.ACTION_PERFORMED) {
  406.             if ((eventMask & AWTEvent.ACTION_EVENT_MASK) != 0 ||
  407.                 actionListener != null) {
  408.                 return true;
  409.             } 
  410.             return false;
  411.         }
  412.         return super.eventEnabled(e);
  413.     }        
  414.  
  415.     /** 
  416.      * Processes action events occurring on this menu item, 
  417.      * by dispatching them to any registered 
  418.      * <code>ActionListener</code> objects.
  419.      * This method is not called unless action events are 
  420.      * enabled for this component. Action events are enabled 
  421.      * when one of the following occurs:
  422.      * <p><ul>
  423.      * <li>An <code>ActionListener</code> object is registered 
  424.      * via <code>addActionListener</code>.
  425.      * <li>Action events are enabled via <code>enableEvents</code>.
  426.      * </ul>
  427.      * @param       e the action event.
  428.      * @see         java.awt.event.ActionEvent
  429.      * @see         java.awt.event.ActionListener
  430.      * @see         java.awt.MenuItem#enableEvents
  431.      * @since       JDK1.1
  432.      */  
  433.     protected void processActionEvent(ActionEvent e) {
  434.         if (actionListener != null) {
  435.             actionListener.actionPerformed(e);
  436.         }
  437.     }
  438.  
  439.     /**
  440.      * Returns the parameter string representing the state of this menu 
  441.      * item. This string is useful for debugging. 
  442.      * @return  the parameter string of this menu item.
  443.      * @since   JDK1.0
  444.      */
  445.     public String paramString() {
  446.         String str = ",label=" + label;
  447.         if (shortcut != null) {
  448.             str += ",shortcut=" + shortcut;
  449.         }
  450.         return super.paramString() + str;
  451.     }
  452.  
  453.  
  454.     /* Serialization support. 
  455.      */
  456.  
  457.     private int menuItemSerializedDataVersion = 1;
  458.  
  459.  
  460.     private void writeObject(ObjectOutputStream s)
  461.       throws IOException 
  462.     {
  463.       s.defaultWriteObject();
  464.  
  465.       AWTEventMulticaster.save(s, actionListenerK, actionListener);
  466.       s.writeObject(null);
  467.     }
  468.  
  469.  
  470.     private void readObject(ObjectInputStream s)
  471.       throws ClassNotFoundException, IOException 
  472.     {
  473.       s.defaultReadObject();
  474.  
  475.       Object keyOrNull;
  476.       while(null != (keyOrNull = s.readObject())) {
  477.     String key = ((String)keyOrNull).intern();
  478.  
  479.     if (actionListenerK == key) 
  480.       addActionListener((ActionListener)(s.readObject()));
  481.  
  482.     else // skip value for unrecognized key
  483.       s.readObject();
  484.       }
  485.     }
  486.  
  487. }
  488.